package book

import (
	"context"
	"time"

	"BookStack/internal/domain/events"
	appErrors "BookStack/pkg/errors"
	"BookStack/pkg/utils"
)

// 获取回收站列表
func (s *service) ListRecycleBin(ctx context.Context, params *RecycleBinQueryParams) (*RecycleBinListResponse, error) {
	// 默认分页参数
	page := 1
	pageSize := 20

	if params != nil {
		if params.Page > 0 {
			page = params.Page
		}
		if params.PageSize > 0 && params.PageSize <= 100 {
			pageSize = params.PageSize
		}
	}

	// 计算偏移量
	offset := (page - 1) * pageSize
	limit := pageSize

	// 构建过滤条件
	filters := make(map[string]interface{})
	if params != nil && params.Type != "" {
		filters["entity_type"] = params.Type
	}

	// 调用领域服务获取回收站列表
	items, total, err := s.bookService.ListRecycleBin(ctx, offset, limit)

	// 处理错误
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	recycleItems := make([]*RecycleBinItem, 0, len(items))
	for _, item := range items {
		recycleItems = append(recycleItems, &RecycleBinItem{
			ID:         item.ID,
			EntityID:   item.ItemID,
			EntityType: item.ItemType,
			Title:      item.Title,
			DeletedAt:  utils.TimeToJSONTime(item.CreatedAt),
			DeletedBy:  item.DeletedBy,
			ParentID:   nil,
		})
	}

	return &RecycleBinListResponse{
		Total: total,
		Items: recycleItems,
	}, nil
}

// 从回收站恢复书籍
func (s *service) RestoreBookFromRecycleBin(ctx context.Context, id uint, restoredBy uint) error {
	// 从回收站获取书籍信息
	book, err := s.RestoreBook(ctx, id, restoredBy)
	if err != nil {
		return err
	}

	// 发布书籍恢复事件
	event := &events.BookRestoredEvent{
		ID:         id,
		Title:      book.Title,
		RestoredBy: restoredBy,
		RestoredAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookRestoredEventType, event))

	return nil
}

// 从回收站恢复章节
func (s *service) RestoreChapterFromRecycleBin(ctx context.Context, id uint, restoredBy uint) error {
	// 从回收站获取章节信息
	chapter, err := s.RestoreChapter(ctx, id, restoredBy)
	if err != nil {
		return err
	}

	// 发布章节恢复事件
	event := &events.ChapterRestoredEvent{
		ID:         id,
		BookID:     chapter.BookID,
		Title:      chapter.Title,
		RestoredBy: restoredBy,
		RestoredAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.ChapterRestoredEventType, event))

	return nil
}

// 批量从回收站恢复项目
func (s *service) BatchRestoreFromRecycleBin(ctx context.Context, req *BatchRestoreRequest, restoredBy uint) (successes []uint, failures map[uint]string, err error) {
	if req == nil || len(req.IDs) == 0 {
		return nil, nil, InvalidRequestError("没有指定要恢复的项目")
	}

	successes = make([]uint, 0)
	failures = make(map[uint]string)

	// 遍历所有ID并尝试恢复
	for _, id := range req.IDs {
		// 尝试获取并恢复书籍
		bookResp, err := s.RestoreBook(ctx, id, restoredBy)
		if err == nil && bookResp != nil {
			successes = append(successes, id)
			continue
		}

		// 如果不是书籍，尝试恢复章节
		chapterResp, err := s.RestoreChapter(ctx, id, restoredBy)
		if err == nil && chapterResp != nil {
			successes = append(successes, id)
			continue
		}

		// 都失败则记录错误
		failures[id] = "无法恢复项目，既不是书籍也不是章节"
	}

	if len(successes) == 0 && len(failures) > 0 {
		return successes, failures, BatchOperationError("所有恢复操作都失败了")
	}

	return successes, failures, nil
}

// PermanentlyDeleteFromRecycleBin 永久删除回收站中的项目
func (s *service) PermanentlyDeleteFromRecycleBin(ctx context.Context, req *PermanentDeleteRequest, deletedBy uint) (successes []uint, failures map[uint]string, err error) {
	if req == nil || len(req.IDs) == 0 {
		return nil, nil, InvalidRequestError("没有指定要删除的项目")
	}

	successes = make([]uint, 0)
	failures = make(map[uint]string)

	// 遍历所有ID并尝试删除
	for _, id := range req.IDs {
		// 尝试获取并删除书籍
		err := s.HardDeleteBook(ctx, id, deletedBy)
		if err == nil {
			successes = append(successes, id)
			continue
		}

		// 如果不是书籍，尝试删除章节
		err = s.HardDeleteChapter(ctx, id, deletedBy)
		if err == nil {
			successes = append(successes, id)
			continue
		}

		// 都失败则记录错误
		failures[id] = "无法删除项目，既不是书籍也不是章节"
	}

	if len(successes) == 0 && len(failures) > 0 {
		return successes, failures, BatchOperationError("所有删除操作都失败了")
	}

	return successes, failures, nil
}

// ClearRecycleBin 清空回收站
func (s *service) ClearRecycleBin(ctx context.Context, deletedBy uint) error {
	// 获取所有回收站项目
	items, _, err := s.bookService.ListRecycleBin(ctx, 0, 1000)
	if err != nil {
		return DatabaseError(err)
	}

	// 如果回收站为空，返回错误
	if len(items) == 0 {
		return RecycleBinEmpty()
	}

	// 调用领域服务清空回收站
	err = s.bookService.ClearRecycleBin(ctx)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeRecycleBinEmpty {
			return RecycleBinEmpty()
		}
		return DatabaseError(err)
	}

	// 发布回收站清空事件
	event := &events.RecycleBinClearedEvent{
		ClearedBy: deletedBy,
		ClearedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.RecycleBinClearedEventType, event))

	return nil
}

// 恢复书籍
func (s *service) RestoreBook(ctx context.Context, id uint, restoredBy uint) (*BookResponse, error) {
	// 恢复书籍
	book, err := s.bookService.RestoreBook(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeRecycleBinItemNotFound {
			return nil, RecycleBinItemNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 发布书籍恢复事件
	event := &events.BookRestoredEvent{
		ID:         book.ID,
		Title:      book.Title,
		RestoredBy: restoredBy,
		RestoredAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookRestoredEventType, event))

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// 恢复章节
func (s *service) RestoreChapter(ctx context.Context, id uint, restoredBy uint) (*ChapterResponse, error) {
	// 恢复章节
	chapter, err := s.bookService.RestoreChapter(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeRecycleBinItemNotFound {
			return nil, RecycleBinItemNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 发布章节恢复事件
	event := &events.ChapterRestoredEvent{
		ID:         chapter.ID,
		BookID:     chapter.BookID,
		Title:      chapter.Title,
		RestoredBy: restoredBy,
		RestoredAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.ChapterRestoredEventType, event))

	// 转换为响应DTO
	return ChapterToResponse(chapter), nil
}

// 永久删除书籍
func (s *service) HardDeleteBook(ctx context.Context, id uint, deletedBy uint) error {
	// 获取书籍信息用于事件发布
	book, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeRecycleBinItemNotFound {
			return RecycleBinItemNotFound(id)
		}
		return DatabaseError(err)
	}

	// 永久删除书籍
	err = s.bookService.HardDeleteBook(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发布书籍永久删除事件
	event := &events.BookHardDeletedEvent{
		ID:            id,
		Title:         book.Title,
		HardDeletedBy: deletedBy,
		HardDeletedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookHardDeletedEventType, event))

	return nil
}

// 永久删除章节
func (s *service) HardDeleteChapter(ctx context.Context, id uint, deletedBy uint) error {
	// 获取章节信息用于事件发布
	chapter, err := s.bookService.GetChapterByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeRecycleBinItemNotFound {
			return RecycleBinItemNotFound(id)
		}
		return DatabaseError(err)
	}

	// 永久删除章节
	err = s.bookService.HardDeleteChapter(ctx, id)
	if err != nil {
		return DatabaseError(err)
	}

	// 发布章节永久删除事件
	event := &events.ChapterHardDeletedEvent{
		ID:            id,
		BookID:        chapter.BookID,
		Title:         chapter.Title,
		HardDeletedBy: deletedBy,
		HardDeletedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.ChapterHardDeletedEventType, event))

	return nil
}
